gdb 的使用记录

记录 gdb 工具。

GDB, the GNU Project debugger, allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed.

安装 debuginfo

debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64

例子

调试可执行文件

// area.cpp
#include <iostream>
using namespace std;

struct Rectangle{
    int width;
    int height;
};

int area(const struct Rectangle& rec) {
    return rec.width * rec.height;
}

int main() {
    Rectangle rec = {10, 20};
    int result = area(rec);
    std::cout << result << std::endl;
    return 0;
}

编译时加上-g 选项,用于生成 debug 信息。

g++ -g ./area.cpp -o area

然后尝试 gdb 打开可执行文件:

gdb area

如果找不到 symbols,可以尝试检查:

nm -C area # 查看symbols
file area # 确认symbols是否剥离(strpped)了

进入交互式环境之后:

(gdb) break area.cpp:9
Breakpoint 1 at 0x4007b5: file ./area.cpp, line 9.

(gdb) run
Starting program: /home/fay/codes/area

Breakpoint 1, area (rec=...) at ./area.cpp:10
10          return rec.width * rec.height;

(gdb) print rec
$1 = (const Rectangle &) @0x7fffffffe4a0: {width = 10, height = 20}

core 文件调试

ulimit -c 1024 # 允许开启core dump,在程序出错时生成core文件
# 确认一下是否生效了
ulimit –c

1024 限制产生的 core 文件的大小不能超过 1024kb,可以使用参数 unlimited,取消该限制

ulimit -c unlimited

随便写一个程序,然后模拟一下:

// fault.cpp
#include <iostream>

int main()
{
    int x = 10/0;
    return 0;
}
g++ -g fault.cpp -o fault
ps -ef|grep "fault" # 找到pid
kill -s SIGSEGV pid # kill 获取core文件
gcore PID # 也可以用gcore获取core文件
gdb forever core.31212

Program terminated with signal 8, Arithmetic exception.
#0  0x000000000040065c in main () at ./fault.cpp:5
5           int x = 10/0;

常用指令

输入 gdb,进入交互式环境。

bt # 查看backtrace,显示当前程序的调用栈(call stack)

info # 显示当前调试状态的各种详细信息
info variables
info variables *param_name*
info locals
info args
info breaks
info frame
info threads

set args           # 设置可执行文件需要或者会用到的参数

break file.cpp:800 # 设置断点
delete breaks      # 删除断点
run                # run 可执行程序
next # 单步执行当前代码行,不进入函数。遇到函数调用时,next 会执行函数,停在函数调用后的下一行。
step # 单步执行当前代码行,如果遇到函数调用,会进入函数内部,逐行执行函数代码。

set print pretty off # 禁用“美化输出”(pretty-printing),显示更简单。
set print array
set print array on

print param_name     # 输出某个变量
print param_name->sub_param

f 9                  # 切换到frame 9
info f

where                # 查看当前位置

thread apply all bt  # 查看所用线程堆栈信息
info threads
thread 1

Q

has no line number information

In my case, the problem was version skew between gcc and gdb.

After landing here from search and none of these answers fit my situation, I figured out that (because of aliases / symlinks / Makefile / environment variables) I was accidentally using a newer GCC (4.8.x) and an older GDB (7.2). Stepping up to a newer version of GDB (7.8) fixed the problem. For some reason, using a newer GCC and older GDB didn't work.

Attempt to dereference a generic pointer

加*

No symbol "i" in current context

I encountered this issue recently. I compiled GCC 5.1 and then used it to compile a C++11 codebase. And, although I could step through the program's code in gdb, I couldn't print the value of any variable, I kept getting “No symbol "xyz" in current context” errors, for every variable.

I was using gdb 7.4, but the latest version available at the time was 7.9. I downloaded the latest version of gdb and compiled it (using GCC 5.1) and when using gdb 7.9 I was able to successfully inspect variable values again.

I guess the debug information of GCC 5.1 is incompatible with gdb 7.4.

break WHERE if COND

eg: linux kernel, stop whenever init got scheduled.

break context_switch if next == init_task

optimized out

The values of arguments that were not saved in their stack frames are shown as `value optimized out'.

Im guessing you compiled with -O(somevalue) and are accessing variables a,b,c in a function where optimization has occurred.

command

specify commands to be run every time you hit a breakpoint.

Memory failure in "?? ()" using GDB

Compile your project with -g -O0 flag. Without -g flag the gcc compiler will strip all the symbol out and that's why you cannot see any symbol. If you want debug 3rd party library then you should configure it with --with-debug or other debug option.

First, getting the complete stack trace here will likely not help you: any crash inside free implementation is due to heap corruption. Here we have heap corruption that GLIBC has already detected and told you about on the console.

Knowing where the corrupted block is being freed usually doesn't help to find where the block was corrupted; use specialized tools like Valgrind or AddressSanitizer for that.

Second, you are not getting file/line info because the crash is happening inside libc.so.6, and you have not installed debuginfo symbols for it. How to install debuginfo depends on your Linux distribution, which you have not told us about.

Last, the reason you have an "apparently corrupt" stack with addresses that don't correspond to any symbols is likely that the calls are coming from hand-coded assembly code (from libopenssl.a), which doesn't use frame pointers and doesn't have correct unwind descriptors. GDB needs one or the other to produce correct stack trace.

please check gdb is codesigned - see taskgated(8)

sudo killall taskgated
codesign -fs gdb-cert "$(which gdb)"

Reference

https://sourceware.org/gdb/current/onlinedocs/gdb/Command-and-Variable-Index.html

No source file named ffmpeg_src/libavcodec/libx264.c.
~~

gdb 的使用记录

例子

Q